//build:20240524
/**
 * This is the base class for UI elements; all other controls inherit from it. Subclasses are not allowed to modify the corresponding function behavior. This JavaScript file does not need to be directly referenced or used.
 */
import utils from "./uiUtils.js"
import logger from './dxLogger.js'
import * as os from "os"
const uibase = {}
/**
* Modify or get the width of the control
* @param {number} w This field is optional. If left blank, it will retrieve the width; otherwise, it will modify the width.
*/
uibase.width = function (w) {
     if (!utils.validateNumber(w)) {
          return this.obj.getWidth()
     }
     this.obj.lvObjSetWidth(w)
}
/**
* Modify or get the height of the control
* @param {number} h This field is optional. If left blank, it will retrieve the height; otherwise, it will modify the height.
*/
uibase.height = function (h) {
     if (!utils.validateNumber(h)) {
          return this.obj.getHeight()
     }
     this.obj.lvObjSetHeight(h)
}
/**
 * Get the width after removing the border and padding.
 * @returns 
 */
uibase.contentWidth = function () {
     return this.obj.lvObjGetContentWidth()
}
/**
 * Get the height after removing the border and padding.
 * @returns 
 */
uibase.contentHeight = function () {
     return this.obj.lvObjGetContentHeight()
}
/**
 * Get the scroll distance above
 * @returns 
 */
uibase.scrollTop = function () {
     return this.obj.getScrollTop()
}
/**
 * Get the scroll distance below
 * @returns 
 */
uibase.scrollBottom = function () {
     return this.obj.getScrollBottom()
}
/**
 * Get the left scroll distance
 * @returns 
 */
uibase.scrollLeft = function () {
     return this.obj.getScrollLeft()
}
/**
 * Get the right scroll distance
 * @returns 
 */
uibase.scrollRight = function () {
     return this.obj.getScrollRight()
}
/**
* Modify the width and height of the control
* @param {number} w Required 
* @param {number} h Required 
*/
uibase.setSize = function (w, h) {
     let err = 'dxui.setSize: width or height should not be empty'
     utils.validateNumber(w, err)
     utils.validateNumber(h, err)
     this.obj.lvObjSetSize(w, h)
}
/**
* Modifying or retrieving the control is equivalent to retrieving the x-coordinate of the parent object.
* @param {number} x This field is optional. If left blank, it retrieves the x-coordinate; otherwise, it modifies the x-coordinate.
*/
uibase.x = function (x) {
     if (!utils.validateNumber(x)) {
          return this.obj.getX()
     }
     this.obj.lvObjSetX(x)
}
/**
* Modifying or retrieving the control is equivalent to retrieving the x-coordinate of the parent object.
* @param {number} y This field is optional. If left blank, it retrieves the y-coordinate; otherwise, it modifies the y-coordinate.
*/
uibase.y = function (y) {
     if (!utils.validateNumber(y)) {
          return this.obj.getY()
     }
     this.obj.lvObjSetY(y)
}
/**
* Modify the x and y coordinates of the control relative to its parent object
* @param {number} x Required 
* @param {number} y Required 
*/
uibase.setPos = function (x, y) {
     let err = 'dxui.setPos: x or y should not be empty'
     utils.validateNumber(x, err)
     utils.validateNumber(y, err)
     this.obj.lvObjSetPos(x, y)
}
/**
 * Moving a control to the top layer means that the last child control created by the parent object will cover all other child controls.
 */
uibase.moveForeground = function () {
     this.obj.moveForeground()
}
/**
 * Moving a control to the bottom layer means that the first child control created by the parent object will be covered by all other child controls.
 */
uibase.moveBackground = function () {
     this.obj.moveBackground()
}
/**
 * Subscribe to events; see utils.EVENT for supported event types.
 * @param {number} type Enumerate utils.EVENT, such as click, long press, etc.
 * @param {function} cb The callback function that triggers the event (cannot be an anonymous function).
 * @param {object} ud User data
 */
uibase.on = function (type, cb, ud) {
     this.obj.addEventCb(() => {
          if (cb) {
               cb({ target: this, ud: ud })
          }
     }, type)
}
/**
 * To send events, such as simulating a button click, you can send a CLICK event to the button.
 * @param {number} type Enumerate utils.EVENT, such as click, long press, etc.
 */
uibase.send = function (type) {
     NativeObject.APP.NativeComponents.NativeEvent.lvEventSend(this.obj, type)
}
/**
 * Hide UI objects
 */
uibase.hide = function () {
     if (!this.obj.hasFlag(1)) {
          this.obj.lvObjAddFlag(1);
     }
}
/**
 * Determine if hidden
 * @returns 
 */
uibase.isHide = function () {
     return this.obj.hasFlag(1);
}
/**
 * Show hidden UI objects
 */
uibase.show = function () {
     if (this.obj.hasFlag(1)) {
          this.obj.lvObjClearFlag(1);
     }
}
/**
 * Disabled Targets
 * @param {*} en `false` or `true`, where `true` disables the function and `false` enables it.
 */
uibase.disable = function (en) {
     if (en) {
          this.obj.addState(utils.STATE.DISABLED)
     } else {
          this.obj.clearState(utils.STATE.DISABLED)
     }
}
/**
 * Is the object clickable?
 * @param {*} en `false/true`, where `true` means clickable and `false` means not clickable.
 */
uibase.clickable = function (en) {
     if (en) {
          this.obj.lvObjAddFlag(utils.OBJ_FLAG.CLICKABLE)
     } else {
          this.obj.lvObjClearFlag(utils.OBJ_FLAG.CLICKABLE)
     }
}
/**
 * Determine whether to disable or enable
 * @returns true means disabled, false means enabled.
 */
uibase.isDisable = function () {
     return this.obj.hasState(utils.STATE.DISABLED)
}
/**
 * Focus object
 * @param {*} en `false/true`, `true` focuses the image, `false` defocuses it.
 */
uibase.focus = function (en) {
     if (en) {
          this.obj.addState(utils.STATE.FOCUSED)
     } else {
          this.obj.clearState(utils.STATE.FOCUSED)
     }
}
/**
 * Determine if focused
 * @returns true indicates focus, false indicates no focus.
 */
uibase.isFocus = function () {
     return this.obj.hasState(utils.STATE.FOCUSED)
}

/**
 * You can set UI styles individually, or you can define a style object first and then bind it to the UI object.
 * Binding UI objects and style objects allows you to bind them to different parts or different states.
 * @param {object} style  The object returned by the build function in style.js
 * @param {number} type  Refer to utils.STYLE. This is not required; by default, it is bound to the object itself.
 */
uibase.addStyle = function (style, type) {
     if (!style || !style.obj) {
          throw new Error('dxui.addStyle: style should not be null')
     }
     if (!utils.validateNumber(type)) {
          type = 0
     }
     this.obj.lvObjAddStyle(style.obj, type);
}
/**
* Set the left, right, top, and bottom paddings to the same value.
* @param {number} pad Margin value
* @param {number} type  Refer to utils.STYLE. This is not required; by default, it is bound to the object itself.
*/
uibase.padAll = function (pad, type) {
     if (!utils.validateNumber(type)) {
          type = 0
     }
     this.obj.lvObjSetStylePadAll(pad, type)
}
/**
 * Setting and getting the right inner margin both use the same value.
 * @param {number} pad Margin value
 * @param {number} type  Refer to utils.STYLE. This is not required; by default, it is bound to the object itself.
 */
uibase.padRight = function (pad, type) {
     if (!utils.validateNumber(type)) {
          type = 0
     }
     if (!utils.validateNumber(pad)) {
          return this.obj.getStylePadRight(type)
     }
     this.obj.setStylePadRight(pad, type)
}
/**
  * Setting/getting the left inner margin both use the same value.
  * @param {number} pad Margin value
  * @param {number} type  Refer to utils.STYLE. This is not required; by default, it is bound to the object itself.
  */
uibase.padLeft = function (pad, type) {
     if (!utils.validateNumber(type)) {
          type = 0
     }
     if (!utils.validateNumber(pad)) {
          return this.obj.getStylePadLeft(type)
     }
     this.obj.setStylePadLeft(pad, type)
}
/**
  * Both setting and getting the top inner margin are set to a single value.
  * @param {number} pad Margin value
  * @param {number} type  Refer to utils.STYLE. This is not required; by default, it is bound to the object itself.
  */
uibase.padTop = function (pad, type) {
     if (!utils.validateNumber(type)) {
          type = 0
     }
     if (!utils.validateNumber(pad)) {
          return this.obj.getStylePadTop(type)
     }
     this.obj.setStylePadTop(pad, type)
}
/**
  * The bottom inner margin is set/retrieved to a single value.
  * @param {number} pad Margin value
  * @param {number} type  Refer to utils.STYLE. This is not required; by default, it is bound to the object itself.
  */
uibase.padBottom = function (pad, type) {
     if (!utils.validateNumber(type)) {
          type = 0
     }
     if (!utils.validateNumber(pad)) {
          return this.obj.getStylePadBottom(type)
     }
     this.obj.setStylePadBottom(pad, type)
}
/**
 * Set/Get Border Width
 * @param {number} w 
 * @param {number} type  Refer to utils.STYLE. This is not required; by default, it is bound to the object itself.
 */
uibase.borderWidth = function (w, type) {
     if (!utils.validateNumber(type)) {
          type = 0
     }
     if (!utils.validateNumber(w)) {
          return this.obj.lvObjGetStyleBorderWidth(type)
     }
     this.obj.lvObjSetStyleBorderWidth(w, type)
}
/**
 * Set border color
 * @param {number} color  Supports numeric types: e.g., 0x34ffaa; and string types (starting with #), e.g., '#34ffaa'.
 * @param {number} type  Refer to utils.STYLE. This is not required; by default, it is bound to the object itself.
 */
uibase.setBorderColor = function (color, type) {
     if (!utils.validateNumber(type)) {
          type = 0
     }
     this.obj.setStyleBorderColor(utils.colorParse(color), type)
}
/**
 * Set corner radius
 * @param {number} r 
 * @param {number} type  Refer to utils.STYLE. This is not required; by default, it is bound to the object itself.
 */
uibase.radius = function (r, type) {
     if (!utils.validateNumber(type)) {
          type = 0
     }
     this.obj.lvObjSetStyleRadius(r, type)
}
/**
 * Set the background transparency; the value ranges from 0 to 100, with lower values ​​being better.
 * @param {number} opa It must be 0-100
 * @param {number} type  Refer to utils.STYLE. This is not required; by default, it is bound to the object itself.
 */
uibase.bgOpa = function (opa, type) {
     if (!utils.validateNumber(type)) {
          type = 0
     }
     this.obj.lvObjSetStyleBgOpa(utils.OPA_MAPPING(opa), type)
}
/**
 * Set background color
 * @param {any} color Supports numeric types: e.g., 0x34ffaa; and string types (starting with #), e.g., '#34ffaa'.
 * @param {number} type  Refer to utils.STYLE. This is not required; by default, it is bound to the object itself.
 */
uibase.bgColor = function (color, type) {
     if (!utils.validateNumber(type)) {
          type = 0
     }
     this.obj.lvObjSetStyleBgColor(utils.colorParse(color), type)
}
/**
 * Set shadow
 * @param {number} width Shadow width
 * @param {number} x Horizontal offset
 * @param {number} y Vertical offset
 * @param {number} spread Diffusion distance
 * @param {number} color color
 * @param {number} opa Transparency must be between 0 and 100.
 * @param {number} type Refer to utils.STYLE. This is not required; by default, it is bound to the object itself.
 */
uibase.shadow = function (width, x, y, spread, color, opa, type) {
     if (!utils.validateNumber(type)) {
          type = 0
     }
     this.obj.lvObjSetStyleShadowWidth(width, type)
     this.obj.lvObjSetStyleShadowOfsX(x, type)
     this.obj.lvObjSetStyleShadowOfsY(y, type)
     this.obj.lvObjSetStyleShadowSpread(spread, type)
     this.obj.setStyleShadowColor(color, type)
     this.obj.setStyleShadowOpa(utils.OPA_MAPPING(opa), type)
}
/**
 * Set text color
 * @param {any} color  Supports numeric types: e.g., 0x34ffaa; and string types (starting with #), e.g., '#34ffaa'.
 * @param {number} type  Refer to utils.STYLE. This is not required; by default, it is bound to the object itself.
 */
uibase.textColor = function (color, type) {
     if (!utils.validateNumber(type)) {
          type = 0
     }
     this.obj.lvObjSetStyleTextColor(utils.colorParse(color), type)
}
/**
 * Set text alignment
 * @param {number} align  See utils.TEXT_ALIGN
 * @param {number} type  Refer to utils.STYLE. This is not required; by default, it is bound to the object itself.
 */
uibase.textAlign = function (align, type) {
     if (!utils.validateNumber(type)) {
          type = 0
     }
     this.obj.lvObjSetStyleTextAlign(align, type)
}
/**
 * Set text font
 * @param {object} font The object returned by build in font.js
 * @param {number} type  Refer to utils.STYLE. This is not required; by default, it is bound to the object itself.
 */
uibase.textFont = function (font, type) {
     if (!utils.validateNumber(type)) {
          type = 0
     }
     if (!font || !font.obj) {
          throw new Error("dxui.textFont: 'font' parameter should not be null")
     }
     this.obj.lvObjSetStyleTextFont(font.obj, type)
}
/**
 * Set the color of the line object.
 * @param {any} color  Supports numeric types: e.g., 0x34ffaa; and string types (starting with #), e.g., '#34ffaa'.
 * @param {number} type  Refer to utils.STYLE. This is not required; by default, it is bound to the object itself.
 */
uibase.lineColor = function (color, type) {
     if (!utils.validateNumber(type)) {
          type = 0
     }
     this.obj.lvObjSetStyleLineColor(utils.colorParse(color), type)
}
/**
 * Set the width of the line object.
 * @param {number} w 
 * @param {number} type  Refer to utils.STYLE. This is not required; by default, it is bound to the object itself.
 */
uibase.lineWidth = function (w, type) {
     if (!utils.validateNumber(type)) {
          type = 0
     }
     this.obj.lvObjSetStyleLineWidth(w, type)
}
/**
 * Set the corner radius of the line object.
 * @param {boolean} enable true/false
 */
uibase.lineRound = function (enable) {
     this.obj.lvObjSetStyleLineRounded(enable)
}
/**
 * Set the scrollbar display method of UI objects
 * @param {boolean} state ture/false 
 */
uibase.scrollbarMode = function (state) {
     this.obj.lvObjSetScrollbarMode(state)
}
/**
 * Configure whether the UI object supports scrolling.
 * @param {boolean} state 
 */
uibase.scroll = function (state) {
     if (state) {
          this.obj.lvObjAddFlag(16)
     } else {
          this.obj.lvObjClearFlag(16)
     }
}
/**
 * Align the object with other reference objects.
 * @param {object} ref Reference object
 * @param {number} type For alignment direction, refer to the dxui.Utils.ALIGN enumeration.
 * @param {number} x offset x
 * @param {number} y offset y
 */
uibase.alignTo = function (ref, type, x, y) {
     if (!ref || !ref.obj) {
          throw new Error("dxui.alignto: 'ref' parameter should not be null")
     }
     this.obj.lvObjAlignTo(ref.obj, type, x, y)
}
/**
 * Align the object with its parent object.
 * @param {number} type For alignment direction, refer to the dxui.Utils.ALIGN enumeration.
 * @param {number} x offset x
 * @param {number} y Offset y
 */
uibase.align = function (type, x, y) {
     this.obj.lvObjAlign(type, x, y)
}
/**
 * The flexbox layout allows for more flexible positioning, arrangement, and distribution of elements, making it easier to create responsive and scalable layouts.
 * It's based on a container and some flexible items inside. Here are some concepts for using this layout:
 * 1. Container: A container contains flexible items that can be arranged in a regular way, such as from left to right or from right to left.
 * 2. Main axis and side axis: The main axis is the primary arrangement of items in the container, usually in the horizontal or vertical direction, allowing items to be arranged horizontally or vertically.
 *   The side axis, which is perpendicular to the main axis, can specify how the items are arranged on the side axis.
 *   The main axis and cross axis are set by flexFlow(), and there are two main types: ROW (horizontal direction) and COLUMN (vertical direction). Items with the WRAP suffix will automatically wrap when they exceed the container, while items with the REVERSE suffix will be arranged in the opposite direction to the default, i.e., from right to left (if the main axis is vertical, then it will be arranged from bottom to top).
 * 3. Main axis alignment: START (default main axis order), END (default main axis order reversed), CENTER (centered along the main axis), SPACE_EVENLY (evenly distributed along the main axis with equal distance between each pair of items), SPACE_AROUND (evenly distributed along the main axis with each item bisecting the distance along the main axis), SPACE_BETWEEN (aligned to the left and right at both ends, with the middle evenly divided), set by flexAlign().
 * 4. Cross axis alignment: Treat each row or column as an item and align it along the cross axis in the same way as the main axis. This is set by flexAlign().
 * 5. Overall alignment: Treats all items within the container as a whole and aligns them within the container in the same way as the main axis. This alignment is set by flexAlign().
 * @param {number} type Spindle and side spindle settings
 */
uibase.flexFlow = function (type) {
     this.obj.lvObjSetFlexFlow(type)
}
/**
 * 
 * @param {number} main Alignment of child elements along the main axis
 * @param {number} cross Alignment of child elements along the cross axis
 * @param {number} track Alignment of all child elements relative to the container
 */
uibase.flexAlign = function (main, cross, track) {
     this.obj.lvObjSetFlexAlign(main, cross, track)
}
/**
 * Update the size of a control. This function can be called first when the size of a control is 0, which is equivalent to updating the display cache.
 */
uibase.update = function () {
     this.obj.lvObjUpdateLayout()
}
/**
 * Add a control's state
 * @param {number} state State Enumeration
 */
uibase.addState = function (state) {
     this.obj.addState(state)
}
/**
 * This method removes the state of a control. For example, to defocus a focused input box, you can call this method to remove the FOCUSED state.
 * @param {number} state State Enumeration
 */
uibase.clearState = function (state) {
     this.obj.clearState(state)
}
/**
 * To determine if a control has a state, such as whether an input field is focused, you can use this method and pass the `FOCUSED` parameter.
 * @param {number} state State Enumeration
 * @returns true/false
 */
uibase.hasState = function (state) {
     return this.obj.hasState(state)
}
/**
 * Redrawing a control and forcibly refreshing its cache can resolve screen flickering issues, but calling this within an infinite loop will degrade performance.
 */
uibase.invalidate = function () {
     this.obj.invalidate()
}
/**
 * This method scrolls a child control until it is visible. If you want to scroll an item that has been scrolled out of the container and is no longer visible, you can call this method.
 * @param {boolean} en Whether to enable animation. If enabled, the animation will scroll out slowly; if disabled, it will jump out immediately.
 * @param {boolean} notRecursive Default recursion, suitable for general scrolling and nested scrolling controls.
 */
uibase.scrollToView = function (en, isRecursive) {
     if (isRecursive) {
          this.obj.scrollToView(en)
     } else {
          this.obj.scrollToViewRecursive(en)
     }
}
/**
 * Scroll a control in the x direction
 * @param {number} x Scrolling x-axis distance
 * @param {boolean} en Enable animation?
 */
uibase.scrollToX = function (x, en) {
     this.obj.scrollToX(x, en)
}
/**
 * Scroll the y-direction of a control
 * @param {number} y Scrolling y-axis distance
 * @param {boolean} en Enable animation
 */
uibase.scrollToY = function (y, en) {
     this.obj.scrollToY(y, en)
}
/**
 * Element snapshot (essentially a screenshot; if you want to save a full-screen screenshot, you can use this method on the screen object).
 * @param {string} fileName Required: The filename for the snapshot (note that the file extension should correspond to the format).
 * @param {number} type Optional field, default is png, snapshot format: 0:bmp/1:png/2:jpg(jpeg)
 * @param {number} cf Optional field, an RGB color storage format
 */
uibase.snapshot = function (fileName, type = 1, cf = NativeObject.APP.NativeComponents.NativeEnum.LV_IMG_CF_TRUE_COLOR_ALPHA) {
     if (!fileName) {
          return
     }
     // By default, it is stored in the /app/data/snapshot location.
     os.mkdir("/app/data/snapshot/")
     this.obj.lvSnapshotTake(cf, "/app/data/snapshot/" + fileName, type)
}
export default uibase;